package wykop.main.configuration;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;

import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

public class Configuration {

	private static class ConfigLine {
		public static ConfigLine parse(final String section, final String line) {
			final List<String> tokens = Lists.newArrayList(Splitter.on('=')
					.split(line));
			final ConfigLine cf = new ConfigLine();
			cf.property = tokens.get(0);
			cf.value = tokens.get(1);
			cf.section = section;
			return cf;
		}

		String section;
		String property;
		String value;
	}

	private static Object extract(final String value, final Class clazz) {
		try {
			if (clazz == Integer.class) {
				return Integer.parseInt(value);
			} else if (clazz == Integer.TYPE) {
				return Integer.parseInt(value);
			} else if (clazz == String.class) {
				return value;
			}
		} catch (final Exception e) {
			throw new RuntimeException(e);
		}
		throw new RuntimeException();
	}

	private static String find(final String section, final String name, final List<ConfigLine> lines) {
		for (final ConfigLine line : lines) {
			if (name.equals(line.property)) {
				return line.value;
			}
		}
		throw new RuntimeException();
	}

	public static <X> X fromFile(final Class<X> clazz, final String path) {
		try { 
			final List<String> lines = Files.readLines(new File(path),
					Charsets.UTF_8);
			final List<ConfigLine> configLines = Lists.newArrayList();
			String section = null;
			for (final String line : lines) {
				if( line.startsWith("#") )
				{
					section = line.substring(1);
				}
				else
				{
					configLines.add(ConfigLine.parse(section,line));
				}
			}

			final X configuration = clazz.newInstance();
			final ConfigurationSection sectionAnnotation = clazz.getAnnotation( ConfigurationSection.class );
			
			if( sectionAnnotation == null)
			{
				throw new RuntimeException("No section defined for this class!");
			}
			
			String sectionName =  sectionAnnotation.value();
			
			final Field[] fields = clazz.getFields();
			for (final Field field : fields) {
				final Property property = field.getAnnotation(Property.class);
				if (property == null) {
					continue;
				}
				final String value = find(sectionName,property.name(), configLines);
				final Object o = extract(value, field.getType());
				field.set(configuration, o);
			}

			return configuration;
		} catch (final IOException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
}
